
#include <glibmm/main.h>

#include <gtkmm/popover.h>
#include <gtkmm/listbox.h>
#include <gtkmm/menubutton.h>

#include "ModuleTaskmanager.h"
#include "Task.h"
#include "App.h"
#include "Mainwin.h"

#include "ServiceTaskmanager.h"


namespace Gnodroid {

    ModuleTaskmanager::ModuleTaskmanager() :
        Glib::ObjectBase("gnd_module_taskmanager"),
        Module(MODULE_TASKMANAGER)
    {}


    void
    ModuleTaskmanager::start()
    {

        auto builder = App::getCurrentApp()->getMainwin()->getBuilder();

        Gtk::MenuButton* mbtnTasklist;

        builder->get_widget("pop_tasklist", m_popTasklist);
        builder->get_widget("listb_tasklist", m_listbTasklist);
        builder->get_widget("mbtn_tasklist", mbtnTasklist);

        //m_popTasklist->set_relative_to(*mbtnTasklist);
        mbtnTasklist->set_popover(*m_popTasklist);

        ServiceTaskmanager* service = static_cast<ServiceTaskmanager*>(App::getService(SERVICE_TASKMANAGER));

        service->signalTaskAdded().connect([this, service](long id) {
            Task* task = service->getTaskById(id);
            //！！内存管理，要删掉这个控件
            auto taskUi = __TaskProgressUi::create();
            taskUi->setTask(task);
            m_listbTasklist->add(*taskUi);
            task->unref();
        });
    }


    void
    ModuleTaskmanager::stop()
    {}


// __TaskProgressUi
    ModuleTaskmanager::__TaskProgressUi*
    ModuleTaskmanager::__TaskProgressUi::create()
    {
        __TaskProgressUi* taskUi = nullptr;
        auto builder = Gtk::Builder::create_from_resource("/org/gnome/Gnodroid/task_progress.ui");
        builder->get_widget_derived("box_main", taskUi);

        return taskUi;
    }

    ModuleTaskmanager::__TaskProgressUi::__TaskProgressUi(BaseObjectType *cobject,
                                        const Glib::RefPtr<Gtk::Builder> &builder) :
        Gtk::Box(cobject),
        m_refBuilder {builder}
    {
        builder->get_widget("lb_label", m_pLbLabel);
        builder->get_widget("lb_message", m_pLbMessage);
        builder->get_widget("btn_control", m_pBtnControl);
        builder->get_widget("prob_progress", m_pProbProgress);


        m_pBtnControl->set_sensitive(false);

    }

    void
    ModuleTaskmanager::__TaskProgressUi::setTask(Task *task)
    {
        m_type = task->getProcessType();
        auto context = App::getMainContext();

        task->signal_label_changed().connect([this](long id, std::string label){
            m_pLbLabel->set_text(label);
        });

        task->signal_message_changed().connect([this](long id, std::string message) {
            m_pLbMessage->set_text(message);
        });


        if (m_type == TaskProgressType::NONE) {
            m_pProbProgress->pulse();
            m_pProbProgress->set_pulse_step(0.1);
            auto timeOutSource = Glib::TimeoutSource::create(500);
            timeOutSource->connect([this]()->bool {
                if (m_state == TaskState::FINNISHED ||
                        m_state == TaskState::ERROR ||
                        m_state == TaskState::BREAK) {
                    return false;
                }
                m_pProbProgress->pulse();
                return true;
            });
            timeOutSource->attach(context);
        } else {
            task->signal_progress_updated().connect([this](long id, TaskProgress prog) {
                m_pProbProgress->set_fraction((prog.current + 0.0) / prog.total);
            });
        }

        //在这里会将任务控件从内存中删除
        task->signal_state_changed().connect([this](long id, TaskState state) {
            m_state = state;
            if (state == TaskState::FINNISHED ||
                    state == TaskState::ERROR ||
                    state == TaskState::BREAK) {
                m_pProbProgress->set_fraction(1.0);
                m_pBtnControl->set_sensitive(true);

                m_pBtnControl->signal_clicked().connect([this](){
                    Gtk::ListBox* parent = static_cast<Gtk::ListBox*>(this->get_parent());
                    if (!parent) {
                        delete this;
                    }
                    //this->hide();
                    parent->remove(*this);
                    delete this;
                });
            }
        });
    }



}
